home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / oldwish / old / wishHandlers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-10  |  26.2 KB  |  932 lines

  1. /* 
  2.  * fsflatHandlers.c --
  3.  *
  4.  *    Event handlers and such for flat display.
  5.  *
  6.  * Copyright 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: fsflatHandlers.c,v 1.1 88/10/03 12:48:12 mlgray Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include "string.h"
  24. #include "util.h"
  25. #include "monitorClient.h"
  26. #include "fsflatInt.h"
  27.  
  28.  
  29. /*
  30.  *----------------------------------------------------------------------
  31.  *
  32.  * FsflatToggleSelection --
  33.  *
  34.  *    Toggle the selection status of an entry.  The event was selected in
  35.  *    the display window, but we are passed the surrounding window.
  36.  *
  37.  * Results:
  38.  *    None.
  39.  *
  40.  * Side effects:
  41.  *    If the coordinates are those of an entry, it is selected if it
  42.  *    wasn't already selected and it is de-selected if it was already
  43.  *    selected.
  44.  *
  45.  *----------------------------------------------------------------------
  46.  */
  47. void
  48. FsflatToggleSelection(window, eventPtr, lineP)
  49.     Window            window;
  50.     XButtonPressedEvent        *eventPtr;
  51.     Boolean            lineP;        /* double click for a line? */
  52. {
  53.     short    x, y;
  54.     FsflatWindow    *aWindow;
  55.     char    buffer[100];
  56.  
  57.     if (eventPtr->type != ButtonPress && eventPtr->type != ButtonRelease) {
  58.     return;
  59.     }
  60.  
  61.     if (XFindContext(fsflatDisplay, window, fsflatWindowContext,
  62.     (caddr_t) &aWindow) != 0) {
  63.     Sx_Panic(fsflatDisplay, "Fsflat didn't recognize given window.");
  64.     }
  65.  
  66.     /* the event was selected in the display window, so coordinates are ok */
  67.     x = ((XButtonEvent *) eventPtr)->x;
  68.     y = ((XButtonEvent *) eventPtr)->y;
  69.  
  70.     sprintf(buffer, "toggleSelection %d %d %d", x, y, lineP);
  71.  
  72.     (void) FsflatDoCmd(aWindow, buffer);
  73.  
  74.     return;
  75. }
  76.  
  77.  
  78. /*
  79.  *----------------------------------------------------------------------
  80.  *
  81.  * FsflatEditRule --
  82.  *
  83.  *    The user has typed something inside a group header entry window.
  84.  *    If he has typed a carriage return, then I take the new string and
  85.  *    try to make it the new selection rule for the window.  If there's
  86.  *    something wrong with the new rule, I tell the user and put back the
  87.  *    old rule. If the rule is ok, I ask him (or will do this soon) whether
  88.  *    he wants to make this rule permanent (put it in his .wish file).
  89.  *    Either way, I go and reselect stuff according to the new rule. For now
  90.  *    I do this the dumb way (I don't just redo the particular group --
  91.  *    I redo all groups), but I'll change it if it's too slow.
  92.  *
  93.  * Results:
  94.  *    None.
  95.  *
  96.  * Side effects:
  97.  *    Many.  Perhaps a new rule set, newly selected files, an edited .wish,
  98.  *    and a newly built display.
  99.  *
  100.  *----------------------------------------------------------------------
  101.  */
  102. void
  103. FsflatEditRule(window, eventPtr)
  104.     Window    window;
  105.     XKeyPressedEvent    *eventPtr;
  106. {
  107.     FsflatWindow    *aWindow;
  108.     FsflatGroup        *groupPtr;
  109.     Boolean        editRuleP = FALSE;
  110.     char        *mapping;
  111.     char        keyString[20];
  112.     int            length;
  113.     char        *buffer;
  114.  
  115.     if (eventPtr->type != KeyPress && eventPtr->type != KeyRelease) {
  116.     return;
  117.     }
  118.     if (XFindContext(fsflatDisplay, window, fsflatWindowContext,
  119.         (caddr_t) &aWindow) != 0) {
  120.     Sx_Panic(fsflatDisplay, "Fsflat didn't recognize given window.");
  121.     }
  122.     if (XFindContext(fsflatDisplay, window, fsflatGroupWindowContext,
  123.         (caddr_t) &groupPtr) != 0) {
  124.     Sx_Panic(fsflatDisplay, "Fsflat didn't recognize given header window.");
  125.     }
  126.     /* Check to see if they've typed a carriage return. */
  127.     length = XLookupString(eventPtr, keyString, 20, (KeySym *) NULL,
  128.         (XComposeStatus *) NULL);
  129.     
  130.     /* John does stuff here to force ctrl chars and meta bits.  Should I? */
  131.     for (mapping = keyString; length > 0; length--) {
  132.     if (*mapping++ == ctrl('m')) {
  133.         editRuleP = TRUE;
  134.         break;
  135.     }
  136.     }
  137.     if (editRuleP == FALSE) {
  138.     return;
  139.     }
  140.     if (groupPtr->defType != COMPARISON) {
  141.     sprintf(fsflatErrorMsg, "%s %s %s.", "Currently it is only possible to",
  142.         "edit the rules graphically for groups defined",
  143.         "with simple comparisons");
  144.     Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  145.         fsflatErrorMsg, NULL, TRUE, "Continue", NULL);
  146.     /* restore header */
  147.     strcpy(groupPtr->editHeader, groupPtr->rule);
  148.     Sx_EntryMake(fsflatDisplay, groupPtr->headerWindow, NULL,
  149.         aWindow->fontPtr, aWindow->foreground, aWindow->background,
  150.         groupPtr->editHeader, sizeof (groupPtr->editHeader));
  151.     return;
  152.     }
  153.     
  154.     buffer = (char *) malloc(strlen("changeGroup") + strlen(groupPtr->rule) +
  155.         strlen("comparison") + strlen(groupPtr->editHeader) + 4); 
  156.  
  157.     sprintf(buffer, "changeGroup %s %s %s", groupPtr->rule,
  158.         "comparison", groupPtr->editHeader);
  159.  
  160.     if (FsflatDoCmd(aWindow, buffer) != TCL_OK) {
  161.     /* restore header */
  162.     strcpy(groupPtr->editHeader, groupPtr->rule);
  163.     Sx_EntryMake(fsflatDisplay, groupPtr->headerWindow, NULL,
  164.         aWindow->fontPtr, aWindow->foreground, aWindow->background,
  165.         groupPtr->editHeader, sizeof (groupPtr->editHeader));
  166.     }
  167.  
  168.     free(buffer);
  169.  
  170.     return;
  171. }
  172.  
  173.  
  174.  
  175. /*
  176.  *----------------------------------------------------------------------
  177.  *
  178.  * FsflatEditDir --
  179.  *
  180.  *    The user has typed something in the directory name window.  If he
  181.  *    has typed a carriage return, then I look at the edited string and try to
  182.  *    make it the new dir of the display.  If the string isn't a valid
  183.  *    file or directory, then we notify them, and redisplay the current
  184.  *    dir. If a proper node has been chosen, call FsflatChangeDir() with it.
  185.  *    The event was selected in the title window, but the window we
  186.  *    are passed is the surrounding window.
  187.  *
  188.  * Results:
  189.  *    None.
  190.  *
  191.  * Side effects:
  192.  *    If a good dir was selected, it becomes the new dir of the display
  193.  *    and we redisplay.
  194.  *
  195.  *----------------------------------------------------------------------
  196.  */
  197. void
  198. FsflatEditDir(window, eventPtr)
  199.     Window        window;
  200.     XKeyPressedEvent    *eventPtr;
  201. {
  202.     struct    stat    dirAtts;
  203.     FsflatWindow    *aWindow;
  204.     int            length;
  205.     Boolean        editDirP = FALSE;
  206.     char        *mapping;
  207.     char        keyString[20];
  208.  
  209.     if (eventPtr->type != KeyPress && eventPtr->type != KeyRelease) {
  210.     return;
  211.     }
  212.     if (XFindContext(fsflatDisplay, window, fsflatWindowContext,
  213.         (caddr_t) &aWindow) != 0) {
  214.     Sx_Panic(fsflatDisplay, "Fsflat didn't recognize a given window.");
  215.     }
  216.     /* Check to see if they've typed a carriage return. */
  217.     length = XLookupString(eventPtr, keyString, 20, (KeySym *) NULL,
  218.         (XComposeStatus *) NULL);
  219.     /* John does stuff here to force ctrl chars and meta bits.  Should I? */
  220.     for (mapping = keyString; length > 0; length--) {
  221.     if (*mapping++ == ctrl('m')) {
  222.         editDirP = TRUE;
  223.         break;
  224.     }
  225.     }
  226.     if (editDirP == FALSE) {
  227.     return;
  228.     }
  229.     /*
  230.      * Put new dir name into canonical form.  If this fails, something is
  231.      * wrong with the new name and we restore the current good one in
  232.      * the title window.
  233.      */
  234.     if (Util_CanonicalDir(aWindow->editDir, aWindow->dir, aWindow->editDir) ==
  235.         NULL) {
  236.     /* error message returned in aWindow->editDir */
  237.     Sx_Notify(fsflatDisplay, aWindow->surroundingWindow, -1, -1, 0,
  238.         aWindow->editDir, NULL, TRUE, "Skip command", (char *) NULL);
  239.     strcpy(aWindow->editDir, aWindow->dir);
  240.     Sx_EntryMake(fsflatDisplay, aWindow->titleWindow, "Directory:  ",
  241.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  242.         aWindow->editDir, sizeof (aWindow->editDir));
  243.  
  244.     return;
  245.     }
  246.  
  247.     /*
  248.      * Check validity of the new dir.  If it's no good, restore the name
  249.      * of the old dir in the title window.
  250.      */
  251.     if (lstat(aWindow->editDir, &dirAtts)
  252.         != 0) {
  253.     sprintf(fsflatErrorMsg,
  254.         "Cannot switch to dir %s.  Maybe it doesn't exist?",
  255.         aWindow->editDir);
  256.     Sx_Notify(fsflatDisplay, aWindow->surroundingWindow, -1, -1, 0,
  257.         fsflatErrorMsg, NULL, TRUE, "Skip command", (char *) NULL);
  258.     strcpy(aWindow->editDir, aWindow->dir);
  259.     Sx_EntryMake(fsflatDisplay, aWindow->titleWindow, "Directory:  ",
  260.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  261.         aWindow->editDir, sizeof (aWindow->editDir));
  262.  
  263.     return;
  264.     }
  265.     if ((dirAtts.st_mode & S_IFMT) != S_IFDIR) {    /* not a directory */
  266.     sprintf(fsflatErrorMsg, "%s is not a directory.", aWindow->editDir);
  267.     Sx_Notify(fsflatDisplay, aWindow->surroundingWindow, -1, -1, 0,
  268.         fsflatErrorMsg, NULL, TRUE, "Skip command", (char *) NULL);
  269.     strcpy(aWindow->editDir, aWindow->dir);
  270.     Sx_EntryMake(fsflatDisplay, aWindow->titleWindow, "Directory:  ",
  271.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  272.         aWindow->editDir, sizeof (aWindow->editDir));
  273.     return;
  274.     }
  275.  
  276.     FsflatChangeDir(aWindow, aWindow->editDir);
  277.  
  278.     return;
  279. }
  280.  
  281.  
  282. /*
  283.  *----------------------------------------------------------------------
  284.  *
  285.  * FsflatChangeDir --
  286.  *
  287.  *     Make the directory of the display be the given directory "where".
  288.  *    If the current directory has been chosen, ignore it since this
  289.  *    won't change anything.  The directory "where" must already have
  290.  *    been canonicalized and checked for existence.
  291.  *
  292.  * Results:
  293.  *    None.
  294.  *
  295.  * Side effects:
  296.  *    If a new directory was selected, it becomes the new diretory of the
  297.  *    display    and we rebuild the display.  The title window is updated to
  298.  *    show the new directory.
  299.  *
  300.  *----------------------------------------------------------------------
  301.  */
  302. void
  303. FsflatChangeDir(aWindow, where)
  304.     FsflatWindow    *aWindow;
  305.     char        *where;        /* Careful -- this parameter may
  306.                      * be aWindow->editDir */
  307. {
  308.     static char     *command = "insert cd";
  309.     char        *insertcommand;
  310.  
  311.     /* if the dir has not changed, just return */
  312.     if (strcmp(aWindow->dir, where) == 0) {
  313.     /* Just refresh titleWindow */
  314.     strcpy(aWindow->editDir, aWindow->dir);
  315.     Sx_EntryMake(fsflatDisplay, aWindow->titleWindow, "Directory:  ",
  316.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  317.         aWindow->editDir, sizeof (aWindow->editDir));
  318.     return;
  319.     }
  320.  
  321.     if (chdir(where) != 0) {
  322.     sprintf(fsflatErrorMsg, "Couldn't change directories to %s", where);
  323.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  324.     }
  325.     if (!MonClient_ChangeDir(aWindow->dir, where)) {
  326.     sprintf(fsflatErrorMsg, "FsflatChangeDir: %s",
  327.         "Changing directories in file system monitor failed.");
  328.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  329.     }
  330.  
  331.     strcpy(aWindow->dir, where);
  332.     /* Change the title to new dir */
  333.     strcpy(aWindow->editDir, aWindow->dir);
  334.     Sx_EntryMake(fsflatDisplay, aWindow->titleWindow, "Directory:  ",
  335.         aWindow->titleFontPtr, aWindow->foreground, aWindow->background,
  336.         aWindow->editDir, sizeof (aWindow->editDir));
  337.  
  338.     /* for window icon */
  339.     XStoreName(fsflatDisplay, aWindow->surroundingWindow, aWindow->dir); 
  340.  
  341.     FsflatGarbageCollect(aWindow);
  342.     /* delete old interpreter and start new one? */
  343.     strcpy(fsflatCurrentDirectory, aWindow->dir);
  344.  
  345.     FsflatSourceConfig(aWindow);
  346.  
  347.     aWindow->firstElement = 1;        /* start displaying from beginning */
  348.     FsflatSetPositions(aWindow);
  349.     /* FsflatRedraw will be called from event caused in FsflatSetPositions() */
  350.     /* throw a cd into tx window, if there is one.  +4 for space,'\n', & '\0' */
  351.     insertcommand = (char *) malloc(strlen(command) +
  352.         strlen(fsflatCurrentDirectory) + 4);
  353.     sprintf(insertcommand, "%s %s\\n", command, fsflatCurrentDirectory);
  354.     Tx_Command(fsflatDisplay, aWindow->txOutsideWindow, insertcommand);
  355.     free(insertcommand);
  356.  
  357.     return;
  358. }
  359.  
  360.  
  361. /*
  362.  *----------------------------------------------------------------------
  363.  *
  364.  * FsflatSourceConfig --
  365.  *
  366.  *     Source the config files to rebuild the display.
  367.  *
  368.  * Results:
  369.  *    None.
  370.  *
  371.  * Side effects:
  372.  *    After a redisplay, anything could be different.
  373.  *
  374.  *----------------------------------------------------------------------
  375.  */
  376. void
  377. FsflatSourceConfig(aWindow)
  378.     FsflatWindow    *aWindow;
  379. {
  380.     char    *environVar;
  381.     char    string[MAXPATHLEN];
  382.     struct    stat    attrs;
  383.     struct    stat    localAttrs;
  384.     FILE    *test;
  385.  
  386.     /*
  387.      * This prevents things that would change the display from doing so
  388.      * until a desired redraw event.
  389.      */
  390.     aWindow->dontDisplayChangesP = TRUE;
  391.     /*
  392.      * The implicit assumption here is that we always try to read a
  393.      * .wish file in the user's home directory.  Then we try to
  394.      * read one in the local directory, if it is different from the home
  395.      * directory.  The local one can override things in the home directory
  396.      * .wish file.  I find this awkward.  I think that it should look first for
  397.      * a local one and tbe local one could source the .wish in the home
  398.      * directory, if the user wishes.  But this is to keep wish compatible
  399.      * with mx and things.
  400.      */
  401.     environVar = (char *) getenv("HOME");
  402.     if (environVar != NULL) {
  403.     sprintf(string, "%s/.wish", environVar);
  404.     /*
  405.      * use open instead of access to test read permission with
  406.      * effictive, rather than real, uid.  How wasteful.
  407.      */
  408.     if ((test = fopen(string, "r")) != NULL) {
  409.         (void) stat(string, &attrs);
  410.         sprintf(string, "source %s/.wish", environVar);
  411.         (void) FsflatDoCmd(aWindow, string);
  412.         (void) fclose(test);
  413.     }
  414.     }
  415.     /* Make sure we don't source the same file twice */
  416.     /* What if results of void'd FsflatDoCmd()'s were not TCL_OK? */
  417.  
  418.     /*
  419.      * use open instead of access to test read permission with
  420.      * effictive, rather than real, uid.  How wasteful.
  421.      */
  422.     if ((test = fopen(".wish", "r")) != NULL) {
  423.     (void) stat(".wish", &localAttrs);
  424.     if (attrs.st_ino != localAttrs.st_ino ||
  425.         attrs.st_dev != localAttrs.st_dev ||
  426.         attrs.st_serverID != localAttrs.st_serverID) {
  427.         (void) FsflatDoCmd(aWindow, "source .wish");
  428.     }
  429.     (void) fclose(test);
  430.     }
  431.  
  432.     /* If no groups from startup files, then get default "*" group. */
  433.     if (aWindow->groupList == NULL) {
  434.     if (FsflatGatherNames(aWindow) != TCL_OK) {
  435.         /* fix here too */
  436.     }
  437.     }
  438.  
  439.     /* now that we're finished sourcing the file, it's okay to update things. */
  440.     aWindow->dontDisplayChangesP = FALSE;
  441.  
  442.     return;
  443. }
  444.  
  445.  
  446.  
  447. /*
  448.  *----------------------------------------------------------------------
  449.  *
  450.  * FsflatHandleDrawingEvent --
  451.  *
  452.  *    Handle an event that requires drawing the display again.
  453.  *
  454.  * Results:
  455.  *    None.
  456.  *
  457.  * Side effects:
  458.  *    The display is drawn again.  If the window has changed size,
  459.  *    the diplay may be different.
  460.  *
  461.  *----------------------------------------------------------------------
  462.  */
  463. void
  464. FsflatHandleDrawingEvent(aWindow, eventPtr)
  465.     FsflatWindow    *aWindow;
  466.     XExposeEvent    *eventPtr;
  467. {
  468.     int    height, width, dummy1;
  469.     Window    dummy2;
  470.     char    buffer[100];
  471.  
  472.     /* ignore events from child windows */
  473.     if (eventPtr->window != aWindow->surroundingWindow && eventPtr->window !=
  474.         aWindow->displayWindow) {
  475.     return;
  476.     }
  477.     switch(eventPtr->type) {
  478.     /* This would only report a child resized, anyway, no? */
  479.     case ConfigureNotify:
  480.     case MapNotify:
  481.     XGetGeometry(fsflatDisplay, aWindow->displayWindow, &dummy2,
  482.         &dummy1, &dummy1, &width, &height, &dummy1, &dummy1);
  483.     if (width != aWindow->windowWidth || height != aWindow->windowHeight) {
  484.         sprintf(buffer, "resize %d %d", height, width);
  485.         (void) FsflatDoCmd(aWindow, buffer);
  486.         return;
  487.     }
  488.     strcpy(buffer, "redraw");
  489.     (void) FsflatDoCmd(aWindow, buffer);
  490.     return;
  491.     case Expose:
  492.     /*
  493.      * Only redraw on the last expose event.
  494.      */
  495.     if (eventPtr->count != 0) {
  496.         return;
  497.     }
  498.     strcpy(buffer, "redraw");
  499.     (void) FsflatDoCmd(aWindow, buffer);
  500.     return;
  501.     default:
  502.     return;
  503.     }
  504. }
  505.  
  506.  
  507.  
  508. /*
  509.  *----------------------------------------------------------------------
  510.  *
  511.  * FsflatHandleDestructionEvent --
  512.  *
  513.  *    Not yet implemented.  Should do garbage collection and such
  514.  *    once I have got that in place.
  515.  *
  516.  * Results:
  517.  *    None.
  518.  *
  519.  * Side effects:
  520.  *    None.
  521.  *
  522.  *----------------------------------------------------------------------
  523.  */
  524. /*ARGSUSED*/
  525. void
  526. FsflatHandleDestructionEvent(aWindow, eventPtr)
  527.     FsflatWindow    *aWindow;
  528.     XExposeEvent    *eventPtr;
  529. {
  530.     return;
  531. }
  532.  
  533.  
  534. /*
  535.  *----------------------------------------------------------------------
  536.  *
  537.  * FsflatMouseEvent --
  538.  *
  539.  *    This routine implements the bindings of various mouse
  540.  *    buttons to various commands.  This routine is temporary and will
  541.  *    go away when the command bindings stuff is done.
  542.  *
  543.  * Results:
  544.  *    None.
  545.  *
  546.  * Side effects:
  547.  *    If a command was chosen, it is executed.
  548.  *
  549.  *----------------------------------------------------------------------
  550.  */
  551. void
  552. FsflatMouseEvent(window, eventPtr)
  553.     Window        window;        /* the surrounding window */
  554.     XButtonEvent    *eventPtr;
  555. {
  556.     static    int    lastWindow = 0;
  557.     static    int    lastTime = 0;
  558.     static    int    repeatCount = 0;
  559.     static    int    lastX = -1;
  560.     static    int    lastY = -1;
  561.     int        x, y;
  562.     FsflatFile    *filePtr;
  563.     FsflatGroup    *groupPtr;
  564.     FsflatWindow    *aWindow;
  565.     int        button = 0;
  566.     char    *selectButton = NULL;
  567.     char    *command;
  568.     char    buffer[100];
  569.  
  570.  
  571. #define    DETAIL_MASK    7
  572.  
  573.     if (eventPtr->subwindow != NULL) {
  574.     return;
  575.     }
  576.     switch (eventPtr->type) {
  577.     case MotionNotify:
  578.     case LeaveNotify:
  579.     /* Highlight mouse movement */
  580.     FsflatHighlightMovement(window, eventPtr);
  581.     return;
  582.     case ButtonPress:
  583.     break;
  584.     default:
  585.     return;
  586.     }
  587.     /* Left button is Button1? */
  588.     if ((eventPtr->button & DETAIL_MASK) == Button1) {
  589.     button |= FSFLAT_LEFT_BUTTON;
  590.     }
  591.     if ((eventPtr->button & DETAIL_MASK) == Button2) {
  592.     button |= FSFLAT_MIDDLE_BUTTON;
  593.     }
  594.     if ((eventPtr->button & DETAIL_MASK) == Button3) {
  595.     button |= FSFLAT_RIGHT_BUTTON;
  596.     }
  597.     /* What to do about meta, shift and double buttons??? */
  598.  
  599.     /*
  600.      * See which group, if any, button is over.  See if it matches a
  601.      * button binding for that group.  If not, see if it matches
  602.      * the selection button.
  603.      */
  604.     
  605.     /* the event was selected in the display window, so coordinates are ok */
  606.     x = ((XButtonEvent *) eventPtr)->x;
  607.     y = ((XButtonEvent *) eventPtr)->y;
  608.  
  609.     if (XFindContext(fsflatDisplay, window, fsflatWindowContext,
  610.         (caddr_t) &aWindow) != 0) {
  611.     Sx_Panic(fsflatDisplay, "Fsflat didn't recognize given window.");
  612.     }
  613.     filePtr = FsflatMapCoordsToFile(aWindow, x, y);
  614.     if (filePtr != NULL) {
  615.     groupPtr = filePtr->myGroupPtr;
  616.     command = FsflatGetGroupBinding(groupPtr, button);
  617.     if (command != NULL) {
  618.         Tcl_SetVar(aWindow->interp, "pointed", filePtr->name, 1);
  619.         /* do it */
  620.         (void) FsflatDoCmd(aWindow, command);
  621.     }
  622.     }
  623.     /* No command, see if selection was meant */
  624.     
  625.     
  626.     /*
  627.      * See if button matches selection button.
  628.      * What do I do about meta's and shifts and such???
  629.      */
  630.     selectButton = Tcl_GetVar(aWindow->interp, "selectionButton", 1);
  631.     if (selectButton == NULL || selectButton[0] == '\0') {
  632.     Tcl_SetVar(aWindow->interp, "selectionButton", "left", 1);
  633.     if (button != FSFLAT_LEFT_BUTTON) {    /* not selection */
  634.         return;
  635.     }
  636.     } else {
  637.     if (button != FsflatWhichButton(selectButton)) {    /* not select.*/
  638.         return;
  639.     }
  640.     }
  641.  
  642.     /* Prof. Ousterhout does drag scrolling here if the shift key is down */
  643.  
  644.     /* Count the number of clicks in the same place. */
  645.     if (lastWindow == window && ((eventPtr->time - lastTime) < 50) &&
  646.         ((lastX + 2) >= eventPtr->x) && ((lastX - 2) <= eventPtr->x) &&
  647.         ((lastY + 2) >= eventPtr->y) && ((lastY - 2) <= eventPtr->y)) {
  648.     repeatCount += 1;
  649.     if (repeatCount > 2) {
  650.         repeatCount = 1;
  651.     }
  652.     } else {
  653.     repeatCount = 1;
  654.     }
  655.     lastX = eventPtr->x;
  656.     lastY = eventPtr->y;
  657.     lastTime = eventPtr->time;
  658.     lastWindow = window;
  659.     switch (repeatCount) {
  660.     case 2:
  661.     /* select line */
  662.     sprintf(buffer, "toggleSelection %d %d 1", x, y);
  663.     (void) FsflatDoCmd(aWindow, buffer);
  664. /*    old...
  665.     FsflatToggleSelection(window, eventPtr, TRUE);
  666.  */
  667.     break;
  668.     default:
  669.     /* select filename */
  670.     sprintf(buffer, "toggleSelection %d %d 0", x, y);
  671.     (void) FsflatDoCmd(aWindow, buffer);
  672. /*    old...
  673.     FsflatToggleSelection(window, eventPtr, FALSE);
  674.  */
  675.     break;
  676.     }
  677.     return;
  678. }
  679.  
  680.  
  681. /*
  682.  *----------------------------------------------------------------------
  683.  *
  684.  * FsflatHandleEnterEvent --
  685.  *
  686.  *    The mouse has entered a window.  Make sure that the current directory
  687.  *    of the program is the directory of that window.
  688.  *
  689.  * Results:
  690.  *    None.
  691.  *
  692.  * Side effects:
  693.  *    The current directory of the program will change to that of the
  694.  *    window, if it is different.
  695.  *
  696.  *----------------------------------------------------------------------
  697.  */
  698. void
  699. FsflatHandleEnterEvent(aWindow, eventPtr)
  700.     FsflatWindow    *aWindow;
  701.     XEnterWindowEvent    *eventPtr;
  702. {
  703.     if (eventPtr->type != EnterNotify) {
  704.     return;
  705.     }
  706.     if (strcmp(fsflatCurrentDirectory, aWindow->dir) == 0) {
  707.     return;
  708.     }
  709.     if (chdir(aWindow->dir) != 0) {
  710.     sprintf(fsflatErrorMsg, "%s %s.  %s %s",
  711.         "Couldn't change back to directory", aWindow->dir,
  712.         "Does it still exist?  This window no longer makes sense",
  713.         "and will now disappear.");
  714.     Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  715.         fsflatErrorMsg, NULL, TRUE, "Continue", NULL);
  716.     (void) FsflatDoCmd(aWindow, "close");
  717.     return;
  718.     }
  719.     strcpy(fsflatCurrentDirectory, aWindow->dir);
  720.  
  721.     return;
  722. }
  723.  
  724.  
  725.  
  726. /*
  727.  *----------------------------------------------------------------------
  728.  *
  729.  * FsflatKeyProc --
  730.  *
  731.  *    This procedure is invoked by the Sx dispatcher whenever a
  732.  *    key is typed in an Fsflat window.
  733.  *
  734.  * Results:
  735.  *    None.
  736.  *
  737.  * Side effects:
  738.  *    Can be almost arbitrary.  Depends completely on the key.
  739.  *
  740.  *----------------------------------------------------------------------
  741.  */
  742. void
  743. FsflatKeyProc(aWindow, eventPtr)
  744.     FsflatWindow    *aWindow;    /* Keeps track of information for
  745.                      * window. */
  746.     XKeyEvent *eventPtr;        /* Describes key that was pressed. */
  747. {
  748.     char    keyString[20];
  749.     char    *command, *mapping;
  750.     register    char    c;
  751.     int        result, nBytes;
  752.     Boolean    undo = TRUE;
  753.     char    insertCommand[20];
  754.     Window    w;
  755.  
  756.     w = aWindow->surroundingWindow;
  757.     if (eventPtr->subwindow != NULL) {
  758.     return;
  759.     }
  760.  
  761.     /*
  762.      * Convert from raw key number to its ASCII equivalent, then pass
  763.      * each equivalent character to the keystroke binder.  Process
  764.      * any commands that are matched this way.
  765.      */
  766.     
  767.     nBytes = XLookupString(eventPtr, keyString, 20, (KeySym *) NULL,
  768.         (XComposeStatus *) NULL);
  769.     /* John does stuff here to force ctrl chars and meta bits.  Should I? */
  770.     for (mapping = keyString; nBytes > 0; nBytes--, mapping++) {
  771.     result = Cmd_MapKey(aWindow->cmdTable, *mapping, &command);
  772.     if (result == CMD_PARTIAL) {
  773.         continue;
  774.     } else if (result == CMD_UNBOUND) {
  775.         char    msg[30];
  776.  
  777.         FsflatCvtToPrintable(command, 30, msg);
  778. #ifdef NOTDEF
  779.         if (aWindow->msgWindow != NULL) {
  780. #endif NOTDEF
  781.         sprintf(fsflatErrorMsg,
  782.             "The keystroke sequence \"%s\" has no function.", msg);
  783.         Sx_Notify(fsflatDisplay, w, -1, -1, 0, fsflatErrorMsg,
  784.             aWindow->fontPtr, TRUE, "Continue", (char *) NULL);
  785.         return;
  786. #ifdef NOTDEF
  787.         } else {
  788.         sprintf(fsflatErrorMsg,
  789.             "The keystroke sequence\n\"%s\"\nhas no function.", msg);
  790.         (void) Sx_Notify(fsflatDisplay, aWindow->surroundingWindow,
  791.             -1, -1, 0, fsflatErrorMsg, aWindow->fontPtr, TRUE,
  792.             "Ignore and go on", NULL);
  793.         }
  794.         break;
  795. #endif NOTDEF
  796.     } else if (result == CMD_OK) {
  797.         if (*command == '!') {
  798.         undo = FALSE;
  799.         command++;
  800.         } else {
  801. #ifdef NOTDEF
  802.         Undo_Mark(aWindow->fileInfoPtr->log);
  803. #endif NOTDEF
  804.         }
  805.  
  806.         /*
  807.          * If the command is "@", then generate an insert command for
  808.          * the last character typed.
  809.          */
  810.  
  811.         if ((command[0] == '@') && (command[1] == 0)) {
  812.         c = *mapping;
  813.         if (isprint(c) && !isspace(c) && (c != '\\')
  814.             && (c != '"') && (c != ';') && (c != '$')) {
  815.             sprintf(insertCommand, "ins %c", c);
  816.         } else {
  817.             int i = c & 0xff;
  818.  
  819.             sprintf(insertCommand, "ins \\%o", i);
  820.         }
  821.         command = insertCommand;
  822.         }
  823.  
  824.         (void) FsflatDoCmd(aWindow, command);
  825. #ifdef NOTDEF
  826.  
  827.         /*
  828.          * Watch out!  The command could have destroyed the window.
  829.          */
  830.     
  831.         if (MxGetMxWindow(w) != aWindow) {
  832.         return;
  833.         }
  834. #endif NOTDEF
  835.     }
  836.     }
  837. }
  838.  
  839.  
  840.  
  841. /*
  842.  *----------------------------------------------------------------------
  843.  *
  844.  * FsflatHandleMonitorUpdates --
  845.  *
  846.  *    This routine should be called whenever the monitor informs us
  847.  *    that a change has occured in a directory we are viewing.
  848.  *    Note that the directory-changing code here is almost identical to
  849.  *    that in FsflatHandlerEnterEvent().  This means I should have
  850.  *    it as a separate routine, soon.
  851.  *
  852.  * Results:
  853.  *    None.
  854.  *
  855.  * Side effects:
  856.  *    The given window will be updated.
  857.  *
  858.  *----------------------------------------------------------------------
  859.  */
  860. void
  861. FsflatHandleMonitorUpdates()
  862. {
  863.     int    windowID;
  864.     int    cc;
  865.     char    *ptr;
  866.     int        numbytes;
  867.     FsflatWindow    *aWindow;
  868.     int        firstElement;
  869. #ifdef MON_DEBUG
  870.     char    buffer[MAXPATHLEN + 1];
  871. #endif MON_DEBUG
  872.  
  873.     ptr = (char *) (&windowID);
  874.     numbytes = sizeof (windowID);
  875.     cc = 0;
  876.     for ( ; cc != -1 && cc < numbytes; numbytes -= cc, ptr += cc) {
  877.     cc = read(monClient_ReadPort, ptr, numbytes);
  878.     }
  879.     if (cc == -1) {
  880.     perror("FsflatHandleMonitorUpdates, windowID read: ");
  881.     exit(1);
  882.     }
  883.  
  884. #ifdef MON_DEBUG
  885.     ptr = buffer;
  886.     numbytes = sizeof (buffer);
  887.     cc = 0;
  888.     for ( ; cc != -1 && cc < numbytes ; numbytes -= cc, ptr += cc) {
  889.     cc = read(monClient_ReadPort, ptr, numbytes);
  890.     if (*(ptr + cc - 1) == '\0') {
  891.         /* came to end of string */
  892.         break;
  893.     }
  894.     }
  895.     if (cc == -1) {
  896.     perror("FsflatHandleMonitorUpdates, path read: ");
  897.     exit(1);
  898.     }
  899. #endif MON_DEBUG
  900.  
  901.     if (XFindContext(fsflatDisplay, windowID, fsflatWindowContext,
  902.         (caddr_t) &aWindow) != 0) {
  903.     Sx_Panic(fsflatDisplay, "Fsflat didn't recognize given window.");
  904.     }
  905.     /*
  906.      * leave aWindow->firstElement the same so that scrolling and such
  907.      * doesn't change.  Later, worry about selection changing.  Also,
  908.      * make sure we're in the same directory as the window we are redoing.
  909.      */
  910.     if (strcmp(fsflatCurrentDirectory, aWindow->dir) != 0) {
  911.     if (chdir(aWindow->dir) != 0) {
  912.         sprintf(fsflatErrorMsg, "%s %s.  %s %s",
  913.             "Couldn't change back to directory", aWindow->dir,
  914.             "Does it still exist?  This window no longer makes",
  915.             "sense and will now disappear.");
  916.         Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  917.             fsflatErrorMsg, NULL, TRUE, "Continue", NULL);
  918.         (void) FsflatDoCmd(aWindow, "close");
  919.         return;
  920.     }
  921.     strcpy(fsflatCurrentDirectory, aWindow->dir);
  922.     }
  923.     firstElement = aWindow->firstElement;
  924.     FsflatGarbageCollect(aWindow);
  925.     FsflatSourceConfig(aWindow);
  926.     aWindow->firstElement = firstElement;
  927.     FsflatSetPositions(aWindow);
  928.     /* FsflatRedraw will be called from event caused in FsflatSetPositions() */
  929.  
  930.     return;
  931. }
  932.